/**
 * @file    drv_can.c
 * @brief   mcu CAN底层驱动
 * @author  Liu Wei
 * @version 1.0.1
 * @date    2023-04-14
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-14 <td>1.0.1     <td>Liu Wei  <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "drv_can.h"
#include "FreeRTOS.h"
#include "task.h"
/* macro/define --------------------------------------------------------------*/

/* typedef -------------------------------------------------------------------*/

/* local functions -----------------------------------------------------------*/

/* static variables ----------------------------------------------------------*/
static CAN_T* can_list[DRV_CAN_MAX] = 
{
    CAN0 ,
    CAN1 ,
};
/* global variables ----------------------------------------------------------*/
static drv_can_cb_pfunc can_int_cb_pfunc[DRV_CAN_MAX] = 
{
    NULL , 
    NULL , 
};
/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  can模块初始化
 * @param  can_speed : CAN波特率
 * @return void
*/
void drv_can_init(uint8_t can_id , uint32_t can_speed)
{
    if(can_id >= DRV_CAN_MAX)
       return ;

    if(DRV_CAN0 == can_id)
    {
		drv_can_deinit(DRV_CAN0);
        /* 开启时钟 */
		CAN0->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
        CAN0->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk));
		CAN0->CON = CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk;
		
        /* 开启时钟 */
		CLK->APBCLK0 |= CLK_APBCLK0_CAN0CKEN_Msk;
        /* CAN0 TX-PD10 RX-PD11*/
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD10MFP_Msk)) | SYS_GPD_MFPH_PD10MFP_CAN0_RXD ;
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD11MFP_Msk)) | SYS_GPD_MFPH_PD11MFP_CAN0_TXD ;
        /* 配置CAN波特率 */
        CAN_Open(CAN0, can_speed , CAN_NORMAL_MODE);

        CAN_EnableInt(CAN0, CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
        NVIC_SetPriority(CAN0_IRQn, (1<<__NVIC_PRIO_BITS) - 3);
        NVIC_EnableIRQ(CAN0_IRQn);
    }
    else if(DRV_CAN1 == can_id)
    {
		drv_can_deinit(DRV_CAN1);
        /* 开启时钟 */
		CAN1->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
        CAN1->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk));
		CAN1->CON = CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk;
		
		CLK->APBCLK0 |= CLK_APBCLK0_CAN1CKEN_Msk;
        /* CAN1 TX-PC13 RX-PD12*/
        SYS->GPC_MFPH = (SYS->GPC_MFPH & ~(SYS_GPC_MFPH_PC13MFP_Msk)) | SYS_GPC_MFPH_PC13MFP_CAN1_TXD ;
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD12MFP_Msk)) | SYS_GPD_MFPH_PD12MFP_CAN1_RXD ;
        /* 配置CAN波特率 */
        CAN_Open(CAN1, can_speed , CAN_NORMAL_MODE);

        CAN_EnableInt(CAN1, CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
        NVIC_SetPriority(CAN1_IRQn, (1<<__NVIC_PRIO_BITS) - 2);
        NVIC_EnableIRQ(CAN1_IRQn);
    }
    else
    {

    }
}   

void drv_can_deinit(uint8_t can_id)
{
	if(DRV_CAN0 == can_id)
	{
		SYS->IPRST1 |= SYS_IPRST1_CAN0RST_Msk;
        SYS->IPRST1 &= ~SYS_IPRST1_CAN0RST_Msk;
        CLK->APBCLK0 &= ~CLK_APBCLK0_CAN0CKEN_Msk;
	}
	else if(DRV_CAN1 == can_id)
	{
	    SYS->IPRST1 |= SYS_IPRST1_CAN1RST_Msk;
        SYS->IPRST1 &= ~SYS_IPRST1_CAN1RST_Msk;
		CLK->APBCLK0 &= ~CLK_APBCLK0_CAN1CKEN_Msk;
	}
}

void drv_can_reset_init(uint8_t can_id , uint32_t can_speed)
{
	if(DRV_CAN0 == can_id)
	{
		CLK->APBCLK0 |= CLK_APBCLK0_CAN0CKEN_Msk;
        /* CAN0 TX-PD10 RX-PD11*/
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD10MFP_Msk)) | SYS_GPD_MFPH_PD10MFP_CAN0_RXD ;
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD11MFP_Msk)) | SYS_GPD_MFPH_PD11MFP_CAN0_TXD ;
        /* 配置CAN波特率 */
		CAN_Open(CAN0, can_speed , CAN_NORMAL_MODE);
		
		CAN_EnableInt(CAN0, CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
	}
	else if(DRV_CAN1 == can_id)
	{
		CLK->APBCLK0 |= CLK_APBCLK0_CAN1CKEN_Msk;
        /* CAN1 TX-PC13 RX-PD12*/
        SYS->GPC_MFPH = (SYS->GPC_MFPH & ~(SYS_GPC_MFPH_PC13MFP_Msk)) | SYS_GPC_MFPH_PC13MFP_CAN1_TXD ;
        SYS->GPD_MFPH = (SYS->GPD_MFPH & ~(SYS_GPD_MFPH_PD12MFP_Msk)) | SYS_GPD_MFPH_PD12MFP_CAN1_RXD ;
        /* 配置CAN波特率 */
		CAN_Open(CAN1, can_speed , CAN_NORMAL_MODE);
		
		CAN_EnableInt(CAN1, CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk);
	}
}
/**
 * @brief  设置CAN接受报文滤波
 * @param  can_id : CAN ID
 * @param  rx_mb : 接受邮箱
 * @param  id_type : ID类型
 * @param  rx_id : 接收ID类型
 * @param  mask_id : 滤波标记位 1:使能 0:无效
 */
void drv_can_set_rx_mb_mask(uint8_t can_id , uint8_t rx_mb , 
                              uint8_t id_type , uint32_t rx_id ,uint32_t mask_id)
{
    if((can_id >= DRV_CAN_MAX) || (rx_mb >= RX_MB_IDM))
        return ;

	CAN_SetRxMsgAndMsk(can_list[can_id] , rx_mb , id_type , rx_id , mask_id);
}

/**
 * @brief  设置CAN回调函数
 * @param  can_id : CAN 编号
 * @param  pfunc : 接受中断回调函数
 */
void drv_can_set_rx_cb_func(uint8_t can_id , drv_can_cb_pfunc pfunc)
{
    if(can_id >= DRV_CAN_MAX)
        return ;

    can_int_cb_pfunc[can_id] = pfunc;
}

/**
 * @brief  can 发送一帧报文
 * @param  send_msg : CAN波特率
 * @return void
*/
uint8_t drv_can_send_frame(uint8_t can_id , can_frame_type send_msg)
{
    STR_CANMSG_T tx_msg = {0};
    uint8_t i = 0;
	uint32_t u32TimeOutCount = 10;
	
    if(can_id >= DRV_CAN_MAX)
        return FALSE;
    
    tx_msg.FrameType = CAN_DATA_FRAME;
    tx_msg.IdType = send_msg.id_type;
    tx_msg.Id = send_msg.id;
    tx_msg.DLC = send_msg.dlc;
    for( i = 0;(i < 8) && (i < send_msg.dlc); ++ i)
    {
        tx_msg.Data[i] = send_msg.data.byte_buf[i];
    }
	
    if(CAN_Transmit(can_list[can_id], MSG(1),&tx_msg) == FALSE)
        return FALSE;
	
	while((CAN_STATUS_TXOK_Msk & can_list[can_id]->STATUS) == 0)
	{
		if(u32TimeOutCount == 0)
		{
//			can_list[can_id]->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk);
//			can_list[can_id]->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk));
//			can_list[can_id]->CON = CAN_CON_IE_Msk|CAN_CON_SIE_Msk | CAN_CON_EIE_Msk;
			break;
		}
		vTaskDelay(1);
		-- u32TimeOutCount;
	}
	
	can_list[can_id]->STATUS &= ~CAN_STATUS_TXOK_Msk;
	
    return TRUE;
}

/**
 * @brief  从接受邮箱中读取一帧数据
 * @param  can_id : CAN ID号
 * @param  mb : 邮箱地址
 * @param  send_msg : 接受的消息
 */
uint8_t drv_can_read_frame(uint8_t can_id ,uint8_t mailbox , can_frame_type *can_msg)
{
    STR_CANMSG_T recv_msg = {0};
	can_frame_type read_msg = {0};
	uint8_t i = 0;
		
    if(can_id >= DRV_CAN_MAX)
        return 0;

    if(0 == CAN_Receive(can_list[can_id] , mailbox , &recv_msg))
		return 
		
	read_msg.frame_type = recv_msg.FrameType;
    read_msg.id_type = recv_msg.IdType;
    read_msg.id = recv_msg.Id;
    read_msg.dlc = recv_msg.DLC;
		
    for( i = 0;(i < 8) && (i < read_msg.dlc); ++ i)
    {
		read_msg.data.byte_buf[i] = recv_msg.Data[i];
    }
	
	*can_msg = read_msg;
	
    return 1;
}

/**
 * @brief  接收中断处理函数
 * @param  can_id : CAN ID号
 * @param  mb : 邮箱地址
 * @param  send_msg : 接受的消息
 */
void drv_can_int_rx_func(uint8_t can_id , uint8_t mailbox) 
{
    can_frame_type recv_msg = {0};

    if(can_id >= DRV_CAN_MAX)
        return ;

    if(0 == drv_can_read_frame(can_id , mailbox , &recv_msg))
		return ;

    if(can_int_cb_pfunc[can_id] != NULL)
    {
        can_int_cb_pfunc[can_id](can_id , recv_msg);
    }
}
/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
